{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 一、感知机的概念\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "感知机也称“人工神经元”。它的作用是**接收多个**输入信号，**输出一个**信号（这里的信号可以理解为数据）。但是，感知机中的信号只有**两种取值0和1**。\n",
    "\n",
    "![image-20230310101155161](https://zyc-learning-1309954661.cos.ap-nanjing.myqcloud.com/machine-learning-pic/image-20230310101155161.png)\n",
    "\n",
    "上图中为一个二输入的感知机，$x_1,x_2$是输入信号，$y$是输出信号，$w_1,w_2$是权重，图里的圆圈代表神经元（**取值只能是0和1**）。\n",
    "\n",
    "输入信号被送往神经元的时候，都会**乘以对应的权重**，然后**求和**。如果**求和结果大于某个阈值**$\\theta$，输出信号$y$才会输出1，这个过程被称为“神经元被激活”。公式如下：\n",
    "\n",
    "![image-20230310101920151](https://zyc-learning-1309954661.cos.ap-nanjing.myqcloud.com/machine-learning-pic/image-20230310101920151.png)\n",
    "\n",
    "感知机的每个输入信号都有各自的权重，**权重**代表了信号的**重要程度**。权重越大，对应该权重的信号的重要性就越高。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 二、感知机与门电路\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "与门真值表：\n",
    "\n",
    "![image-20230310103412515](https://zyc-learning-1309954661.cos.ap-nanjing.myqcloud.com/machine-learning-pic/image-20230310103412515.png)\n",
    "\n",
    "设计感知机，就是确定$w_1,w_2,\\theta$的值，计算式如下：\n",
    "\n",
    "<img src=\"https://zyc-learning-1309954661.cos.ap-nanjing.myqcloud.com/machine-learning-pic/QQ%E5%9B%BE%E7%89%8720230310103853.jpg\" alt=\"QQ图片20230310103853\" style=\"zoom:25%;\" />\n",
    "\n",
    "即：两个权重都不大于阈值，且权重之和大于阈值。\n",
    "\n",
    "其他门电路转感知机的步骤与这个一致，就不详细叙述了。\n",
    "\n",
    "在上述过程中，可以发现确定感知机参数的不是计算机，而是**人根据真值表（训练数据），想出参数的值**。而机器学习的目标就是把这个过程让计算机自动完成，而人需要做的就是确定感知机的构造（确定模型），并把训练数据交给机器。\n",
    "\n",
    "**在门电路的例子中，与门、或门、与非门等门电路的构造都是一样的（二输入一输出），只要改变参数和阈值就能实现不同的功能。**"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 三、感知机的实现\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "使用python来实现刚刚的逻辑电路。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "0\n",
      "0\n",
      "1\n"
     ]
    }
   ],
   "source": [
    "# 定义与门函数\n",
    "def AND(x1, x2):\n",
    "    # 确定参数\n",
    "    w1, w2, theta = 0.5, 0.5, 0.9\n",
    "\n",
    "    # 确定感知机结构\n",
    "    y = w1 * x1 + w2 * x2\n",
    "    if y <= theta:\n",
    "        y = 0\n",
    "    else:\n",
    "        y = 1\n",
    "\n",
    "    # 返回输出结果\n",
    "    return y\n",
    "\n",
    "\n",
    "# 测试\n",
    "print(AND(0, 0))\n",
    "print(AND(1, 0))\n",
    "print(AND(0, 1))\n",
    "print(AND(1, 1))\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "【tips】：上述感知机只要修改权重和阈值，就能实现其他的二输入一输出门电路。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 四、权重和偏执项\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "把感知机的公式改写成如下形式（阈值变为$b$并移项，虽然形式不同但表达的意思不变）：\n",
    "\n",
    "![image-20230310111350098](https://zyc-learning-1309954661.cos.ap-nanjing.myqcloud.com/machine-learning-pic/image-20230310111350098.png)\n",
    "\n",
    "其中，$b$称为偏置项。\n",
    "\n",
    "下面使用numpy实现该公式表达的感知机："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-04T12:29:58.499734Z",
     "start_time": "2023-04-04T12:29:58.346544Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "0\n",
      "0\n",
      "1\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "\n",
    "# 使用numpy实现与门\n",
    "\n",
    "\n",
    "def AND(x1, x2):\n",
    "    # 确定参数\n",
    "    x = np.array([x1, x2])\n",
    "    w = np.array([0.5, 0.4])\n",
    "    b = -0.8\n",
    "\n",
    "    # 确定网络结构\n",
    "    tmp = np.sum(x * w) + b\n",
    "    if tmp <= 0:\n",
    "        y = 0\n",
    "    else:\n",
    "        y = 1\n",
    "\n",
    "    return y\n",
    "\n",
    "\n",
    "# 测试\n",
    "print(AND(0, 0))\n",
    "print(AND(1, 0))\n",
    "print(AND(0, 1))\n",
    "print(AND(1, 1))\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 权重：控制神经元的重要程度\n",
    "- 偏置项：控制神经元被激活的难易程度"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 五、感知机的局限性\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "使用感知机实现异或门。真值表如下：\n",
    "\n",
    "![image-20230310164256034](https://zyc-learning-1309954661.cos.ap-nanjing.myqcloud.com/machine-learning-pic/image-20230310164256034.png)\n",
    "\n",
    "代入感知机的模型，得出权重和偏置项表达式如下：\n",
    "\n",
    "<img src=\"https://zyc-learning-1309954661.cos.ap-nanjing.myqcloud.com/machine-learning-pic/1.png\" alt=\"1\" style=\"zoom:25%;\" />\n",
    "\n",
    "经过观察发现，这个不等式组不可能成立。理由如下：\n",
    "\n",
    "$b≤0、b+x_2>0$ 推出 $x_2>0$ \n",
    "\n",
    "又$b+x_1>0$ 推出 $b+x_1+x_2>0$\n",
    "\n",
    "与$b+x_1+x_2≤0$矛盾"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "从感知机公式中可以看出，最核心的是这个式子$b+x_1w_1+x_2w_2>0$（决定了y的输出），这是一个二元一次不等式，在二维坐标系上对$x_1x_2$画图，图像必然为一条斜率小于0的直线，且在该直线的上方和下方的区域$y$取值都是0或1。图像如下：\n",
    "\n",
    "![image-20230310173701995](https://zyc-learning-1309954661.cos.ap-nanjing.myqcloud.com/machine-learning-pic/image-20230310173701995.png)\n",
    "\n",
    "$(x_1,x_2,y)$的取值一共有四个，图中圆圈代表y取值为0，三角代表取值y为1。由**二输入感知机**的公式可以得到结论：**感知机的必要条件是对能够找到一条斜率<0的直线，将不同输出区分开来。**\n",
    "\n",
    "所以异或门的输入输出对在图中应该是这个样子：\n",
    "\n",
    "![image-20230310174738332](https://zyc-learning-1309954661.cos.ap-nanjing.myqcloud.com/machine-learning-pic/image-20230310174738332.png)\n",
    "\n",
    "显然，没办法找到一条斜率<0的直线，将不同输出区分开来，所以感知机不成立。但是能通过一条曲线，将两个不同输出分隔开：\n",
    "\n",
    "![image-20230310175114929](https://zyc-learning-1309954661.cos.ap-nanjing.myqcloud.com/machine-learning-pic/image-20230310175114929.png)\n",
    "\n",
    "- 由曲线分割而成的空间称为**非线性空间**。\n",
    "- 由直线分割而成的空间称为**线性空间**。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 六、多层感知机\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "可以通过感知机的**叠加**（多层感知机）来实现异或门。\n",
    "\n",
    "即问题转换成：**使用与门、与非门、或门组合成一个异或门（这三个门都能用感知机表示）**\n",
    "\n",
    "![image-20230310180721834](https://zyc-learning-1309954661.cos.ap-nanjing.myqcloud.com/machine-learning-pic/image-20230310180721834.png)\n",
    "\n",
    "![image-20230310180737782](https://zyc-learning-1309954661.cos.ap-nanjing.myqcloud.com/machine-learning-pic/image-20230310180737782.png)\n",
    "\n",
    "使用numpy实现异或门："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "1\n",
      "0\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "\n",
    "# 与门\n",
    "\n",
    "\n",
    "def AND(x1, x2):\n",
    "    x = np.array([x1, x2])\n",
    "    w = np.array([0.5, 0.4])\n",
    "    b = -0.8\n",
    "    tmp = np.sum(x * w) + b\n",
    "    if tmp <= 0:\n",
    "        return 0\n",
    "    else:\n",
    "        return 1\n",
    "\n",
    "\n",
    "# 与非门\n",
    "\n",
    "\n",
    "def NAND(x1, x2):\n",
    "    x = np.array([x1, x2])\n",
    "    w = np.array([-0.5, -0.5])\n",
    "    b = 0.7\n",
    "    tmp = np.sum(x * w) + b\n",
    "    if tmp <= 0:\n",
    "        return 0\n",
    "    else:\n",
    "        return 1\n",
    "\n",
    "\n",
    "# 或门\n",
    "\n",
    "\n",
    "def OR(x1, x2):\n",
    "    x = np.array([x1, x2])\n",
    "    w = np.array([0.5, 0.5])\n",
    "    b = -0.2\n",
    "    tmp = np.sum(x * w) + b\n",
    "    if tmp <= 0:\n",
    "        return 0\n",
    "    else:\n",
    "        return 1\n",
    "\n",
    "\n",
    "# 异或门\n",
    "\n",
    "\n",
    "def EOR(x1, x2):\n",
    "    return AND(NAND(x1, x2), OR(x1, x2))\n",
    "\n",
    "\n",
    "print(EOR(0, 0))\n",
    "print(EOR(1, 0))\n",
    "print(EOR(0, 1))\n",
    "print(EOR(1, 1))\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "用感知机表示异或门如下：\n",
    "\n",
    "![image-20230310184853985](https://zyc-learning-1309954661.cos.ap-nanjing.myqcloud.com/machine-learning-pic/image-20230310184853985.png)\n",
    "\n",
    "感知机是一种非常简单的算法，很快就能理解它的构造。感知机是下一章要学习的神经网络的基础，因此非常重要。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pythonProject",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
